﻿using Colorful.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using MongoDB.Bson;
using Colorful.Database;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Colorful.CMS.Core;
using System.Text.RegularExpressions;

namespace Colorful
{
    public static class ControllerExtensions
    {
        #region 输出

        #region GetJsonResult Json输出
        /// <summary>
        /// 获取Json输出
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="controller"></param>
        /// <param name="data">要转换为Json的对象</param>
        /// <param name="jsonFilter">Json处理回调</param>
        /// <returns></returns>
        public static IActionResult GetJsonResult<T>(this Controller controller, T data, Func<string, string> jsonFilter = null)
        {
            var userAgent = controller.Request.Headers["User-Agent"];
            var mediaType = new MediaTypeHeaderValue("application/json");
            if (!string.IsNullOrEmpty(userAgent))
            {
                var match = Regex.Match(userAgent, "MSIE ([0-9.]*)");
                if (match.Success && match.Groups[1].Value.ToDecimal() < 10)
                    mediaType.MediaType = "text/html";
            }
            mediaType.Encoding = Encoding.UTF8;
            var json = JsonHelper.ToJson(data);
            if (jsonFilter != null)
                json = jsonFilter(json);
            return new ContentResult() { Content = json, ContentType = mediaType.ToString() };
        }
        #endregion

        #region GetTextResult
        public static IActionResult GetTextResult(this Controller controller, string content)
        {
            var mediaType = new MediaTypeHeaderValue("text/html");
            mediaType.Encoding = Encoding.UTF8;
            return new ContentResult() { Content = content, ContentType = mediaType.ToString() };
        }
        #endregion

        #region GetTreeResult
        public static IActionResult GetTree<T>(this Controller controller, List<Tree<T>> treeDatas, string defaultText = "全选")
        {
            return controller.GetJsonResult(new List<Tree<T>>()
            {
                new Tree<T>
                {
                    text = defaultText,
                    id = default(T),
                    expand = true,
                    children = treeDatas
                }
            }, json =>
            {
                return json.Replace("Checked", "checked");
            });
        }
        #endregion

        #region GetResult 获取输出结果
        public static IActionResult GetResult(this Controller controller, bool succ = true, string message = "")
        {
            return controller.GetJsonResult(new { succ = succ, data = message });
        }
        public static IActionResult GetResult<T>(this Controller controller, bool succ, T data)
        {
            return controller.GetJsonResult(new { succ = succ, data = data });
        }
        public static IActionResult GetResult(this Controller controller, Colorful.Models.JsonResult jsonData)
        {
            return controller.GetJsonResult(jsonData);
        }
        public static IActionResult GetResult(this Controller controller, Exception ex, bool showError = false)
        {
            string message;
            if (ex is InvalidException)
                message = ex.Message;
            //else if (ex is HttpRequestValidationException)
            //    message = "您输入的表单有危险字符，请检查后重试！\r\n危险字符：" + ex.Message;
            else
            {
                controller.HttpContext.WriteError(ex);
                if (showError)
                    message = ex.Message;
                else
                    message = "意外错误，请稍后重试！";
            }
            return controller.GetJsonResult(new { succ = false, data = message });
        }
        #endregion

        #region GetDataGrid DataGrid输出
        /// <summary>
        /// 输入为DataGrid格式
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="controller"></param>
        /// <param name="q"></param>
        /// <param name="filter"></param>
        /// <returns></returns>
        public static IActionResult GetDataGrid<T>(this Controller controller, IQueryable<T> q, Func<List<T>, dynamic> filter = null)
        {
            if (q == null)
                return controller.GetJsonResult(new { count = 0, data = new List<T>() });
            var page = controller.Request.Form["page"].ToString().ParseInt() ?? 1;
            if (page < 1) page = 1;
            page--;
            var pagesize = controller.Request.Form["pagesize"].ToString().ParseInt() ?? 10;
            List<T> list;
            if (pagesize > 0)
                list = q.Skip(page * pagesize).Take(pagesize).ToList();
            else
                list = q.ToList();
            if (typeof(T).Name == "BsonDocument")
            {
                var json = new StringBuilder("{\"count\":" + q.Count() + ",\"data\":[");
                foreach (var doc in (list as List<MongoDB.Bson.BsonDocument>))
                {
                    json.Append("{");
                    foreach (var item in doc)
                    {
                        if (item.Value == null || item.Value == BsonNull.Value) continue;

                        json.Append($"\"{(item.Name == "_id" ? "Id" : item.Name)}\":\"{(item.Value.IsValidDateTime ? item.Value.ToLocalTime().ToString("yyyy/MM/dd HH:mm:ss") : item.Value)}\",");
                    }
                    json.Remove(json.Length - 1, 1);
                    json.Append("},");
                }
                if (json.ToString().EndsWith(","))
                    json.Remove(json.Length - 1, 1);
                json.Append("]}");
                var mediaType = new MediaTypeHeaderValue("application/json");
                mediaType.Encoding = Encoding.UTF8;
                return new ContentResult() { Content = json.ToString(), ContentType = mediaType.ToString() };
            }
            else
            {
                return controller.GetJsonResult(new
                {
                    count = q.Count(),
                    data = filter == null ? list : filter(list)
                });
            }
        }
        #endregion

        #endregion

        #region 日志

        public static void WriteDebug(this Controller controller, string message, string category = null)
        {
            controller.HttpContext.WriteDebug(message, category);
        }
        public static void WriteWarn(this Controller controller, string message, string category = null)
        {
            controller.HttpContext.WriteWarn(message, category);
        }
        public static void WriteLog(this Controller controller, string message, string category = null)
        {
            controller.HttpContext.WriteLog(message, category);
        }
        public static void WriteError(this Controller controller, Exception ex, string message, string category = null)
        {
            controller.HttpContext.WriteError(ex, message, category);
        }
        public static void WriteError(this Controller controller, Exception ex, string category = null)
        {
            controller.HttpContext.WriteError(ex, category);
        }

        #endregion
    }
}
